# -*- coding:utf-8 -*-
# created on 2017/4/30
#

from mathsolver.functions.xiangliang.Vector_SanJiaoXing.Vector_SanJiao_Axis_Update import *
from mathsolver.functions.xiangliang.Vector_SanJiaoXing.base import *
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve, MathematicaSimplify
from mathsolver.functions.process import ProcessExpression
from mathsolver.functions.xiangliang.basic import xl_search_multiple, xl_solutions_subs
from sympy import cos, sin
from sympy.abc import theta


class XLSanJiaoGetExpress001(BaseFunction):
    """
    # 在直角△ABC中,G是△ABC的重心,A是△ABC的直角顶点,|\\overrightarrow{AB}|=2,|\\overrightarrow{AC}|=1,
    # 则\\overrightarrow{AG}•\\overrightarrow{BC}=
    1.直角三角形类 or 等腰直角三角形类
    """
    def solver(self, *args):
        assert len(args) == 2
        p1, p2, p3 = args[0].value
        name = p1 + p2 + p3
        assert name in self.known
        sjx = self.search(name)
        assert sjx
        sjx_type = sjx.type
        assert sjx_type == "vRectangularTriangle" or sjx_type == "vIsoscelesRectangularTriangle"
        new_known = dict(self.known)
        stepsolver1 = XLBuildRectangularTriangleAxis(new_known).solver(name)
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        sjx = stepsolver1.output[0]
        if sjx.point_Gravity_name:
            sjx.get_gravity_axis()
        target = args[1].sympify()
        v_eqs = sjx.Eqs
        u_eqs = [[target, 0]]
        u_eqs.extend(v_eqs)
        stepsolver2 = XLSanJiaoXingKnownUpdate(new_known).solver(u_eqs, sjx)
        self.steps += stepsolver2.steps
        new_known = stepsolver2.output[0]
        condition_veqs = []
        for eq in v_eqs:
            if len(eq) == 2:
                new_eqs = XLSanJiaoXingAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eqs = XLSanJiaoXingAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            if len(condition_veqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        if isinstance(args[0], BaseVector):
            left = condition_target[0]
            left_answers = xl_search_multiple(solutions, left)
            assert left_answers
            left_values = []
            for left_answer in left_answers:
                new_left = left
                new_left = new_left.subs(left_answer)
                new_left = MathematicaSimplify().solver(BasePoly(new_left)).output[0].sympify()
                left_values.append(new_left)
            left_values = set(left_values)
            left_values = list(left_values)
            right = condition_target[1]
            right_answers = xl_search_multiple(solutions, right)
            assert right_answers
            right_values = []
            for right_answer in right_answers:
                new_right = right
                new_right = new_right.subs(right_answer)
                new_right = MathematicaSimplify().solver(BasePoly(new_right)).output[0].sympify()
                right_values.append(new_right)
            right_values = set(right_values)
            right_values = list(right_values)
            self.steps.append(["", "∴%s为%s" % (new_latex(target), "或".join(["(%s, %s)" % (new_latex(left_v), new_latex(right_v)) for left_v, right_v in zip(left_values, right_values)]))])
            target_values = []
            for left_v, right_v in zip(left_values, right_values):
                target_values.append([left_v, right_v])
            self.output.append(BaseVector(target_values))
        else:
            target_values = xl_solutions_subs(solutions, condition_target)
            self.steps.append(
                ["", "∴ %s" % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
            self.output.append(BaseNumbers(target_values))
        self.label.add("向量运算-坐标法")
        return self


class XLSanJiaoGetExpress002(BaseFunction):
    """
    # 在边长为1的等边△ABC中,设\\overrightarrow{BC}=2\\overrightarrow{BD},\\overrightarrow{CA}=3\\overrightarrow{CE},
    # 则\\overrightarrow{AD}•\\overrightarrow{BE}=
    1.正三角形类
    """
    def solver(self, *args):
        assert len(args) == 2
        p1, p2, p3 = args[0].value
        name = p1 + p2 + p3
        assert name in self.known
        sjx = self.search(name)
        assert sjx
        sjx_type = sjx.type
        assert sjx_type == "vRegularTriangle"
        new_known = dict(self.known)
        stepsolver1 = XLBulidRegularTriangleAxis(new_known).solver(name)
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        sjx = stepsolver1.output[0]
        if sjx.point_Gravity_name:
            sjx.get_gravity_axis()
        target = args[1].sympify()
        v_eqs = sjx.Eqs
        u_eqs = [[target, 0]]
        u_eqs.extend(v_eqs)
        stepsolver2 = XLSanJiaoXingKnownUpdate(new_known).solver(u_eqs, sjx)
        self.steps += stepsolver2.steps
        new_known = stepsolver2.output[0]
        condition_veqs = []
        for eq in v_eqs:
            if len(eq) == 2:
                new_eqs = XLSanJiaoXingAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eqs = XLSanJiaoXingAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            if len(condition_veqs[0]) == 2:
                self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
            else:
                self.steps.append(["", "%s" % BaseIneq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        if isinstance(args[0], BaseVector):
            left = condition_target[0]
            left_answers = xl_search_multiple(solutions, left)
            assert left_answers
            left_values = []
            for left_answer in left_answers:
                new_left = left
                new_left = new_left.subs(left_answer)
                new_left = MathematicaSimplify().solver(BasePoly(new_left)).output[0].sympify()
                left_values.append(new_left)
            left_values = set(left_values)
            left_values = list(left_values)
            right = condition_target[1]
            right_answers = xl_search_multiple(solutions, right)
            assert right_answers
            right_values = []
            for right_answer in right_answers:
                new_right = right
                new_right = new_right.subs(right_answer)
                new_right = MathematicaSimplify().solver(BasePoly(new_right)).output[0].sympify()
                right_values.append(new_right)
            right_values = set(right_values)
            right_values = list(right_values)
            self.steps.append(["", "∴%s为%s" % (new_latex(target), "或".join(["(%s, %s)" % (new_latex(left_v), new_latex(right_v)) for left_v, right_v in zip(left_values, right_values)]))])
            target_values = []
            for left_v, right_v in zip(left_values, right_values):
                target_values.append([left_v, right_v])
            self.output.append(BaseVector(target_values))
        else:
            target_values = xl_solutions_subs(solutions, condition_target)
            self.steps.append(["", "∴ %s" % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
            self.output.append(BaseNumbers(target_values))
        self.label.add("向量运算-坐标法")
        return self


class XLSanJiaoGetExpress003(BaseFunction):
    """
    # 已知点F是△ABC外心,AB=4,AF=3,则\\overrightarrow{AB}•\\overrightarrow{AC}的取值范围是
    1.三角形+外心类
    2.vEqs非空
    3.坐标法
    """
    def solver(self, *args):
        assert 'vCircumcenterTriangle' in self.known
        known = self.known
        v_wxsjx = known['vCircumcenterTriangle']
        v_eqs = v_wxsjx.Eqs
        assert v_eqs
        target = args[0].sympify()
        point_a = v_wxsjx.A
        point_b = v_wxsjx.B
        point_c = v_wxsjx.C
        circum_center = v_wxsjx.CircumCenter
        line_to_a_name = v_wxsjx.line_To_A_name
        line_to_b_name = v_wxsjx.line_To_B_name
        line_to_c_name = v_wxsjx.line_To_C_name
        u_eqs = []
        jian_xi_flag = [0, 0, 0]  # line_to_a_name, line_to_b_name, line_to_c_name为底边
        for eq in v_eqs:
            if str(eq[0].func) == str("line"):
                left_p, right_p = eq[0].args
                name1 = str(left_p) + str(right_p)
                name2 = str(right_p) + str(left_p)
                if line_to_a_name in [name1, name2]:
                    line_to_a_value = eq[1]
                    v_wxsjx.line_To_A_value = line_to_a_value
                    jian_xi_flag[0] = 1
                elif line_to_b_name in [name1, name2]:
                    line_to_b_value = eq[1]
                    v_wxsjx.line_To_B_value = line_to_b_value
                    jian_xi_flag[1] = 1
                elif line_to_c_name in [name1, name2]:
                    line_to_c_value = eq[1]
                    v_wxsjx.line_To_C_value = line_to_c_value
                    jian_xi_flag[2] = 1
                elif circum_center in [str(left_p), str(right_p)]:
                    other_p = {str(left_p), str(right_p)} - set(circum_center)
                    other_p = list(other_p)[0]
                    if other_p in [point_a, point_b, point_c]:
                        circum_circle_r = eq[1]
                        v_wxsjx.CircumCircle_R = circum_circle_r
                    else:
                        u_eqs.append(eq)
                else:
                    u_eqs.append(eq)
        assert sum(jian_xi_flag) != 0
        if jian_xi_flag[0] == 1:
            self.steps.append(["", "以%s为坐标原点, 平行于%s的直线为x轴, 建立平面直角坐标系" % (new_latex(circum_center), new_latex(line_to_a_name))])
        elif jian_xi_flag[1] == 1:
            self.steps.append(["", "以%s为坐标原点, 平行于%s的直线为x轴, 建立平面直角坐标系" % (new_latex(circum_center), new_latex(line_to_b_name))])
        else:
            self.steps.append(["", "以%s为坐标原点, 平行于%s的直线为x轴, 建立平面直角坐标系, 则" % (new_latex(circum_center), new_latex(line_to_c_name))])
            line_to_c_value = v_wxsjx.line_To_C_value
            circum_circle_r = v_wxsjx.CircumCircle_R
            point_a_axis = BasePoint({"name": point_a, "value": [- line_to_c_value / 2, sqrt(circum_circle_r ** 2 - (line_to_c_value / 2) ** 2)]})
            point_b_axis = BasePoint({"name": point_b, "value": [line_to_c_value / 2, sqrt(circum_circle_r ** 2 - (line_to_c_value / 2) ** 2)]})
            point_c_axis = BasePoint({"name": point_c, "value": [circum_circle_r * cos(theta), circum_circle_r * sin(theta)]})
            v_wxsjx.A_Axis = point_a_axis
            v_wxsjx.B_Axis = point_b_axis
            v_wxsjx.C_Axis = point_c_axis
            v_wxsjx.CircumCenter_Axis = BasePoint({"name": args[0].value, "value": [0, 0]})
            self.steps.append(["", "∴%s, %s" % (point_a_axis.printing(), point_b_axis.printing())])
            self.steps.append(["", "∵点%s在以%s为半径的圆上," % (new_latex(point_c), new_latex(circum_circle_r))])
            self.steps.append(["", "∴设%s" % (point_c_axis.printing())])
        assert not u_eqs
        u_eqs.append([target, 0])
        new_known = XLSanJiaoXingKnownUpdate(known, u_eqs, v_wxsjx)
        condition_target = ProcessExpression(new_known).solver(BaseValue(str(target))).output[0].sympify()
        self.steps.append(["", "∴%s = %s" % (new_latex(target), new_latex(condition_target))])
        self.output.append(BaseNumbers([condition_target]))
        self.label.add("向量运算-坐标法")
        return self


class XLSanJiaoGetExpress(BaseFunction):
    CLS = [XLSanJiaoGetExpress001, XLSanJiaoGetExpress002]

    def solver(self, *args):
        known = self.known
        r = None
        for cl in XLSanJiaoGetExpress.CLS:
            try:
                r = cl(known, verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r
